package com.bj;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.casino.tool.CSM;
import com.casino.tool.P;

public class Strategy {
	public static final int ERROR = -1;
	public static final int HIT = 1;
	public static final int SURRENDER = 2;
	public static final int HOLD = 3;
	public static final int DOUBLEBET = 4;
	public static final int SPLITE = 5;
	public static final int BUST = 6;

	private static boolean isPair(List<P> myCards, boolean canNotSplit) {

		if (canNotSplit) {
			return false;
		}

		if ((myCards.get(0).getNum() != 14 && myCards.get(0).getNum() >= 10) && (myCards.get(1).getNum() != 14 && myCards.get(1).getNum() >= 10)) {
			return true;
		}

		if (myCards.size() == 2 && myCards.get(0).getNum() == myCards.get(1).getNum()) {
			return true;
		} else {
			return false;
		}
	}

	public static boolean getNightCall(P dealerP, List<P> myCards) {

		if (myCards.get(0).getNum() == 2) {
			if (dealerP.getNum() == 4 || dealerP.getNum() == 5 || dealerP.getNum() == 6 || dealerP.getNum() == 7) {
				return true;
			}
		} else if (myCards.get(0).getNum() == 3) {
			if (dealerP.getNum() == 4 || dealerP.getNum() == 5 || dealerP.getNum() == 6) {
				return true;
			}
		} else if (myCards.get(0).getNum() == 4) {
			if (dealerP.getNum() == 5 || dealerP.getNum() == 6) {
				return true;
			}
		} else if (myCards.get(0).getNum() == 5) {
			if (dealerP.getNum() == 6) {
				return true;
			}
		} else if (myCards.get(0).getNum() == 6) {
			if (dealerP.getNum() == 5 || dealerP.getNum() == 6) {
				return true;
			}
		} else if (myCards.get(0).getNum() == 7) {
			if (dealerP.getNum() == 4 || dealerP.getNum() == 5 || dealerP.getNum() == 6) {
				return true;
			}
		} else if (myCards.get(0).getNum() == 8) {
			if (dealerP.getNum() <= 7) {
				return true;
			}
		} else if (myCards.get(0).getNum() == 9) {
			if (dealerP.getNum() <= 8) {
				return true;
			}
		} else {
			return false;
		}
		return false;
	}

	public static void main(String[] args) {

		int dealerFirstCard = Integer.parseInt(args[0]);
		int playerFirstCard = Integer.parseInt(args[1]);
		int playerSecondCard = Integer.parseInt(args[2]);
		// int playerThirdCard = Integer.parseInt(args[3]);
		int addRealCount = Integer.parseInt(args[3]);
		int minusRealCount = Integer.parseInt(args[4]);

		// int dealerFirstCard = 10;
		// int playerFirstCard = 10;
		// int playerSecondCard = 4;
		// // int playerThirdCard = Integer.parseInt(args[3]);
		// int addRealCount = 0;
		// int minusRealCount = 0;

		int hitValue = 0;
		int holdValue = 0;

		for (int rt = 0; rt < 2; rt++) {

			CSM csm = new CSM(6, 25);

			int lossCount = 0;
			int winCount = 0;

			for (int i = 0; i < 10000000; i++) {
				// for (int j = 0; j < 17; j++) {
				// csm.dealRandomCard();
				// }
				csm.dealSpeicalCard(8);
				for (int add = 0; add < addRealCount; add++) {
					csm.dealSpeicalCard(MathUtil.randomNum(5) + 2);
				}

				for (int minus = 0; minus < minusRealCount; minus++) {
					csm.dealSpeicalCard(MathUtil.randomNum(5) + 10);
				}

				P p = csm.dealSpeicalCard(dealerFirstCard);
				P p1 = csm.dealSpeicalCard(playerFirstCard);
				P p2 = csm.dealSpeicalCard(playerSecondCard);

				List<P> dealerPList = new ArrayList<P>();

				dealerPList.add(p);

				List<P> l = new ArrayList<P>();
				l.add(p1);
				l.add(p2);

				if (rt == 0) {

					int st = Strategy.getBasicStrategy(p, l, false, false, false, -100);
					while (st == Strategy.HIT) {
						l.add(csm.dealRandomCard());
						st = Strategy.getBasicStrategy(p, l, false, false, false, -100);
					}

				} else {

				}

				// while (true) {
				// int s = Strategy.getBasicStrategy(p, l, false, false, false);
				// if(s==Strategy.HIT){
				// l.add(csm.dealRandomCard());
				// }else{
				// break;
				// }
				// }

				while (Dealer.isHit(dealerPList)) {
					P ps = csm.dealRandomCard();
					dealerPList.add(ps);
				}

				int rPoint = -1;
				if (Strategy.count(l) > 21) {
					lossCount++;
				} else if (Strategy.count(dealerPList) == 21 && dealerPList.size() == 2) {
					lossCount++;
				} else if (Strategy.count(dealerPList) > 21) {
					winCount++;
				} else {
					rPoint = Strategy.count(l);
					if (Strategy.count(dealerPList) > rPoint) {

						lossCount++;

					} else if (Strategy.count(dealerPList) < rPoint) {

						winCount++;
					}
				}
				csm.returnCardsToMachine();
				//
				// p.print();
				// System.out.println("");
				// for (P sp : l) {
				// sp.print();
				// System.out.print(" ");
				// }
				// System.out.println("");
				// System.out.println(getBasicStrategy(p, l, false, false,
				// false));
				// System.out.println("-------");
			}
			if (rt == 0) {
				hitValue = winCount - lossCount;
				System.out.println("hit:" + (winCount - lossCount));
			} else {
				holdValue = winCount - lossCount;
				System.out.println("hold:" + (winCount - lossCount));
			}

		}
		if (hitValue - holdValue > 0) {
			System.out.println("hit better");
		} else {
			System.out.println("hold better");
		}
	}

	public static int getBasicStrategy(P dealerP, List<P> myCards, boolean hasSplite, boolean canNotSplit, boolean hasNight, double hiloCount) {
		int countNow = count(myCards);
		boolean hasA = hasA(myCards);
		boolean hasPair = isPair(myCards, canNotSplit);
		if (countNow >= 22) {
			return BUST;
		}
		if ((!hasA && !hasPair)) {
			if (countNow <= 8) {
				return HIT;
			} else if (countNow == 9) {
				if ((dealerP.getNum() == 3 || dealerP.getNum() == 4 || dealerP.getNum() == 5 || dealerP.getNum() == 6) && Rule.isDoubleAble(myCards)) {
					return DOUBLEBET;
				} else {
					return HIT;
				}
			} else if (countNow == 10) {
				if (dealerP.getNum() <= 9 && Rule.isDoubleAble(myCards)) {
					return DOUBLEBET;
				} else {
					return HIT;
				}
			} else if (countNow == 11) {
				if (dealerP.getNum() <= 13 && Rule.isDoubleAble(myCards)) {
					return DOUBLEBET;
				} else if (dealerP.getNum() == 14) {
					if (hiloCount >= 6) {
						return DOUBLEBET;
					} else {
						return HIT;
					}
				} else {
					return HIT;
				}
			} else if (countNow == 12) {
				if (dealerP.getNum() == 4 || dealerP.getNum() == 5 || dealerP.getNum() == 6) {
					return HOLD;
				} else {
					return HIT;
				}
			} else if (countNow == 13) {
				if (dealerP.getNum() == 2) {
					if (hiloCount <= -2) {
						return HIT;
					} else {
						return HOLD;
					}

				} else if (dealerP.getNum() <= 6) {
					return HOLD;
				} else {
					return HIT;
				}
			} else if (countNow == 14) {
				if (dealerP.getNum() <= 6) {
					return HOLD;
				} else if (dealerP.getNum() >= 10) {
					if (Rule.isSurrenderAble(myCards, dealerP)) {
						if (hiloCount >= -2) {
							return SURRENDER;
						} else {
							return HIT;
						}

					} else {
						return HIT;
					}
				} else {
					return HIT;
				}
			} else if (countNow == 15) {
				if (dealerP.getNum() >= 10) {
					if (Rule.isSurrenderAble(myCards, dealerP)) {
						return SURRENDER;
					} else {
						return HIT;
					}
				} else if (dealerP.getNum() == 2 || dealerP.getNum() == 3 || dealerP.getNum() == 4 || dealerP.getNum() == 5 || dealerP.getNum() == 6) {
					return HOLD;
				} else {
					return HIT;
				}

			} else if (countNow == 16) {
				if (dealerP.getNum() == 9) {
					if (Rule.isSurrenderAble(myCards, dealerP)) {
						return SURRENDER;
					} else {
						return HIT;
					}
				} else if (dealerP.getNum() == 14) {
					if (Rule.isSurrenderAble(myCards, dealerP)) {
						return SURRENDER;
					} else {
						return HIT;
					}
				} else if (dealerP.getNum() >= 10) {
					if (Rule.isSurrenderAble(myCards, dealerP)) {
						return SURRENDER;
					} else {
						if (hiloCount > 0) {
							return HOLD;
						} else {
							return HIT;
						}
						// return HOLD;
					}
				} else if (dealerP.getNum() == 2 || dealerP.getNum() == 3 || dealerP.getNum() == 4 || dealerP.getNum() == 5 || dealerP.getNum() == 6) {
					return HOLD;
				} else {
					return HIT;
				}

			} else if (countNow >= 17) {
				return HOLD;
			}
		} else if (hasA && hasPair) {
//			if (hasSplite) {
//				return HOLD;
//			} else {
				return SPLITE;
//			}

		} else if (hasA) {

			if (hasSplite && myCards.get(0).getNum() == 14) {
				return HOLD;
			}

			if (dealerP.getNum() == 2) {
				return getDealer2Strategy(myCards, countNow);
			} else if (dealerP.getNum() == 3) {
				return getDealer3Strategy(myCards, countNow);
			} else if (dealerP.getNum() == 4) {
				return getDealer4Strategy(myCards, countNow);
			} else if (dealerP.getNum() == 5) {
				return getDealer5Strategy(myCards, countNow);
			} else if (dealerP.getNum() == 6) {
				return getDealer6Strategy(myCards, countNow);
			} else if (dealerP.getNum() == 7) {
				return getDealer7Strategy(myCards, countNow);
			} else if (dealerP.getNum() == 8) {
				return getDealer8Strategy(myCards, countNow);
			} else if (dealerP.getNum() == 9) {
				return getDealer9Strategy(myCards, countNow);
			} else if (dealerP.getNum() == 10 || dealerP.getNum() == 11 || dealerP.getNum() == 12 || dealerP.getNum() == 13) {
				return getDealer10Strategy(myCards, countNow);
			} else if (dealerP.getNum() == 14) {
				return getDealer11Strategy(myCards, countNow);
			}

		} else if (hasPair) {

			if (hasNight) {

				if (myCards.get(0).getNum() == 2) {
					if (dealerP.getNum() == 4 || dealerP.getNum() == 5 || dealerP.getNum() == 6 || dealerP.getNum() == 7) {
						return SPLITE;
					} else {
						return HIT;
					}
				} else if (myCards.get(0).getNum() == 3) {
					if (dealerP.getNum() == 4 || dealerP.getNum() == 5 || dealerP.getNum() == 6) {
						return SPLITE;
					} else {
						return HIT;
					}
				} else if (myCards.get(0).getNum() == 4) {
					if (dealerP.getNum() == 5 || dealerP.getNum() == 6) {
						return SPLITE;
					} else {
						return HIT;
					}
				} else if (myCards.get(0).getNum() == 5) {
					if (dealerP.getNum() == 6) {
						return SPLITE;
					} else {
						if (dealerP.getNum() <= 9) {
							return DOUBLEBET;
						} else {
							return HIT;
						}
					}
				} else if (myCards.get(0).getNum() == 6) {
					if (dealerP.getNum() == 5 || dealerP.getNum() == 6) {
						return SPLITE;
					} else {
						if (dealerP.getNum() == 2 || dealerP.getNum() == 3) {
							return HIT;
						} else if (dealerP.getNum() >= 7) {
							return HIT;
						} else {
							return HOLD;
						}
					}
				} else if (myCards.get(0).getNum() == 7) {
					if (dealerP.getNum() == 4 || dealerP.getNum() == 5 || dealerP.getNum() == 6) {
						return SPLITE;
					} else {
						if (dealerP.getNum() <= 3) {
							return HOLD;
						} else if (dealerP.getNum() == 14) {
							return HIT;
						} else if (dealerP.getNum() >= 10) {
							return SURRENDER;
						} else {
							return HIT;
						}
					}
				} else if (myCards.get(0).getNum() == 8) {
					if (dealerP.getNum() <= 7) {
						return SPLITE;
					} else {
						if (dealerP.getNum() == 14) {
							return HIT;
						} else if (dealerP.getNum() >= 10) {
							return SURRENDER;
						} else {
							return HIT;
						}
					}
				} else if (myCards.get(0).getNum() == 9) {
					if (dealerP.getNum() <= 8) {
						return SPLITE;
					} else {
						return HOLD;
					}
				} else if (myCards.get(0).getNum() == 10 || myCards.get(0).getNum() == 11 || myCards.get(0).getNum() == 12 || myCards.get(0).getNum() == 13) {
					return HOLD;
				}
			} else {

				if (myCards.get(0).getNum() == 8) {
					if (dealerP.getNum() == 14) {
						return SPLITE;
					} else if (dealerP.getNum() >= 10) {
						if (Rule.isSurrenderAble(myCards, dealerP)) {
							return SURRENDER;
						} else {
							return HIT;
						}
					} else {
						return SPLITE;
					}
				} else if (myCards.get(0).getNum() == 5) {
					if (dealerP.getNum() < 10 && Rule.isDoubleAble(myCards)) {
						return DOUBLEBET;
					} else {
						return HIT;
					}

				} else if (myCards.get(0).getNum() >= 10) {
					return HOLD;
				} else if (myCards.get(0).getNum() == 2 || myCards.get(0).getNum() == 3 || myCards.get(0).getNum() == 7) {
					if (dealerP.getNum() == 2 || dealerP.getNum() == 3 || dealerP.getNum() == 4 || dealerP.getNum() == 5 || dealerP.getNum() == 6 || dealerP.getNum() == 7) {
						return SPLITE;
					} else {
						return HIT;
					}

				} else if (myCards.get(0).getNum() == 4) {
					if (dealerP.getNum() == 5 || dealerP.getNum() == 6) {
						return SPLITE;
					} else {
						return HIT;
					}
				} else if (myCards.get(0).getNum() == 6) {
					if (dealerP.getNum() == 4 || dealerP.getNum() == 5 || dealerP.getNum() == 6 || dealerP.getNum() == 3 || dealerP.getNum() == 2) {
						return SPLITE;
					} else {
						return HIT;
					}
				} else if (myCards.get(0).getNum() == 9) {
					if (dealerP.getNum() == 7 || dealerP.getNum() >= 10) {
						return HOLD;
					} else {
						return SPLITE;
					}
				}
			}
		}
		return ERROR;
	}

	public static int getNightStrategy(P dealerP, double rCount, int spliteTimes, Game.Round round, boolean canNotSplit) {

		List<P> myCards = round.getpList();
		int countNow = count(myCards);
		boolean hasA = hasA(myCards);
		boolean hasPair = isPair(myCards, canNotSplit);

		if (countNow >= 22) {
			return BUST;
		}

		if ((!hasA && !hasPair)) {

			if (countNow <= 8) {
				return HIT;
			} else if (countNow == 9) {
				if ((dealerP.getNum() == 3 || dealerP.getNum() == 4 || dealerP.getNum() == 5 || dealerP.getNum() == 6) && Rule.isDoubleAble(myCards)) {
					return DOUBLEBET;
				} else {
					return HIT;
				}
			} else if (countNow == 10) {
				if (dealerP.getNum() <= 9 && Rule.isDoubleAble(myCards)) {
					return DOUBLEBET;
				} else {
					return HIT;
				}
			} else if (countNow == 11) {
				if (dealerP.getNum() <= 13 && Rule.isDoubleAble(myCards)) {
					return DOUBLEBET;
				} else {
					return HIT;
				}
			} else if (countNow == 12) {
				if (dealerP.getNum() == 4 || dealerP.getNum() == 5 || dealerP.getNum() == 6) {
					return HOLD;
				} else {
					return HIT;
				}
			} else if (countNow == 13) {
				if (dealerP.getNum() <= 6) {
					return HOLD;
				} else {
					return HIT;
				}
			} else if (countNow == 14) {
				if (dealerP.getNum() <= 6) {
					return HOLD;
				} else if (dealerP.getNum() >= 10) {
					if (Rule.isSurrenderAble(myCards, dealerP)) {
						return SURRENDER;
					} else {
						return HIT;
					}
				} else {
					return HIT;
				}
			} else if (countNow == 15) {
				if (dealerP.getNum() >= 10) {
					if (Rule.isSurrenderAble(myCards, dealerP)) {
						return SURRENDER;
					} else {
						return HIT;
					}
				} else if (dealerP.getNum() == 2 || dealerP.getNum() == 3 || dealerP.getNum() == 4 || dealerP.getNum() == 5 || dealerP.getNum() == 6) {
					return HOLD;
				} else {
					return HIT;
				}

			} else if (countNow == 16) {
				if (dealerP.getNum() >= 9) {
					if (Rule.isSurrenderAble(myCards, dealerP)) {
						return SURRENDER;
					} else {
						return HIT;
					}
				} else if (dealerP.getNum() == 2 || dealerP.getNum() == 3 || dealerP.getNum() == 4 || dealerP.getNum() == 5 || dealerP.getNum() == 6) {
					return HOLD;
				} else {
					return HIT;
				}

			} else if (countNow >= 17) {
				return HOLD;
			}
		} else if (hasA && hasPair) {
			return SPLITE;
		} else if (hasA) {

			if (round.isHasSplite()) {
				return HOLD;
			}

			if (dealerP.getNum() == 2) {
				return getDealer2Strategy(myCards, countNow);
			} else if (dealerP.getNum() == 3) {
				return getDealer3Strategy(myCards, countNow);
			} else if (dealerP.getNum() == 4) {
				return getDealer4Strategy(myCards, countNow);
			} else if (dealerP.getNum() == 5) {
				return getDealer5Strategy(myCards, countNow);
			} else if (dealerP.getNum() == 6) {
				return getDealer6Strategy(myCards, countNow);
			} else if (dealerP.getNum() == 7) {
				return getDealer7Strategy(myCards, countNow);
			} else if (dealerP.getNum() == 8) {
				return getDealer8Strategy(myCards, countNow);
			} else if (dealerP.getNum() == 9) {
				return getDealer9Strategy(myCards, countNow);
			} else if (dealerP.getNum() == 10 || dealerP.getNum() == 11 || dealerP.getNum() == 12 || dealerP.getNum() == 13) {
				return getDealer10Strategy(myCards, countNow);
			} else if (dealerP.getNum() == 14) {
				return getDealer11Strategy(myCards, countNow);
			}

		} else if (hasPair) {

			if (myCards.get(0).getNum() == 5) {
				if (dealerP.getNum() < 10 && Rule.isDoubleAble(myCards)) {
					return DOUBLEBET;
				} else {
					return HIT;
				}

			} else if (myCards.get(0).getNum() == 4) {
				if (dealerP.getNum() == 5 || dealerP.getNum() == 6) {
					return SPLITE;
				} else {
					return HIT;
				}

			} else if (myCards.get(0).getNum() == 9) {
				if (dealerP.getNum() == 7) {
					return HOLD;
				} else {
					return SPLITE;
				}

			} else if (myCards.get(0).getNum() >= 10) {
				return HOLD;
			} else {
				return SPLITE;
			}
		}
		return ERROR;
	}

	public static int count(List<P> pList) {
		int count = 0;
		boolean hasA = false;
		for (P p : pList) {
			if (p.getNum() == 14) {
				count = count + 1;
				hasA = true;
			} else if (p.getNum() >= 10) {
				count = count + 10;
			} else {
				count = count + p.getNum();
			}
		}

		if (hasA && count <= 11) {
			count = count + 10;
		}
		return count;
	}

	public static boolean hasA(List<P> pList) {
		boolean hasA = false;
		for (P p : pList) {
			if (p.getNum() == 14) {
				hasA = true;
			}
		}
		int count = 0;
		for (P p : pList) {
			if (p.getNum() == 14) {
				count = count + 1;
			} else if (p.getNum() >= 10) {
				count = count + 10;
			} else {
				count = count + p.getNum();
			}
		}
		if (count + 10 >= 22) {
			hasA = false;
		}

		return hasA;
	}

	private static int getDealer2Strategy(List<P> myCards, int countNow) {
		if (countNow >= 18) {
			return HOLD;
		} else {
			return HIT;
		}

	}

	private static int getDealer3Strategy(List<P> myCards, int countNow) {
		if (countNow == 17) {
			if (Rule.isDoubleAble(myCards)) {
				return DOUBLEBET;
			} else {
				return HIT;
			}
		} else if (countNow == 18) {
			if (Rule.isDoubleAble(myCards)) {
				return DOUBLEBET;
			} else {
				return HOLD;
			}
		} else if (countNow >= 19) {
			return HOLD;
		} else {
			return HIT;
		}
	}

	private static int getDealer4Strategy(List<P> myCards, int countNow) {
		if (countNow == 15 || countNow == 16 || countNow == 17) {
			if (Rule.isDoubleAble(myCards)) {
				return DOUBLEBET;
			} else {
				return HIT;
			}
		} else if (countNow == 18) {
			if (Rule.isDoubleAble(myCards)) {
				return DOUBLEBET;
			} else {
				return HOLD;
			}
		} else if (countNow >= 19) {
			return HOLD;
		} else {
			return HIT;
		}
	}

	private static int getDealer5Strategy(List<P> myCards, int countNow) {
		if (countNow >= 19) {
			return HOLD;
		} else if (countNow == 18) {
			if (Rule.isDoubleAble(myCards)) {
				return DOUBLEBET;
			} else {
				return HOLD;
			}
		} else {
			if (Rule.isDoubleAble(myCards)) {
				return DOUBLEBET;
			} else {
				return HIT;
			}
		}

	}

	private static int getDealer6Strategy(List<P> myCards, int countNow) {
		if (countNow >= 19) {
			return HOLD;
		} else if (countNow == 18) {
			if (Rule.isDoubleAble(myCards)) {
				return DOUBLEBET;
			} else {
				return HOLD;
			}
		} else {
			if (Rule.isDoubleAble(myCards)) {
				return DOUBLEBET;
			} else {
				return HIT;
			}
		}

	}

	private static int getDealer7Strategy(List<P> myCards, int countNow) {
		if (countNow >= 18) {
			return HOLD;
		} else {
			return HIT;
		}

	}

	private static int getDealer8Strategy(List<P> myCards, int countNow) {
		if (countNow >= 18) {
			return HOLD;
		} else {
			return HIT;
		}

	}

	private static int getDealer9Strategy(List<P> myCards, int countNow) {
		if (countNow >= 19) {
			return HOLD;
		} else {
			return HIT;
		}

	}

	private static int getDealer10Strategy(List<P> myCards, int countNow) {
		if (countNow >= 19) {
			return HOLD;
		} else {
			return HIT;
		}

	}

	private static int getDealer11Strategy(List<P> myCards, int countNow) {
		if (countNow >= 19) {
			return HOLD;
		} else {
			return HIT;
		}

	}

}
